﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using EnvDTE80;

namespace SD007
{
    public class DteSpike
    {
        private DTE2 _applicationObject;
        public DteSpike(DTE2 _applicationObject)
        {
            this._applicationObject = _applicationObject;
        }

        public void HowToUseCodeModelSpike()
        {
            // get the DTE reference...
            DTE2 dte2 = _applicationObject;

            // get the solution
            Solution solution = dte2.Solution;
            // find this file and examine it
            if(dte2.ActiveDocument != null && dte2.ActiveDocument.ProjectItem != null)
                ExamineItem(dte2.ActiveDocument.ProjectItem);
        }

        

        // examine an item
        private void ExamineItem(ProjectItem item)
        {
            FileCodeModel2 model = (FileCodeModel2)item.FileCodeModel;            
            foreach(CodeElement codeElement in model.CodeElements)
            {
                ExamineCodeElement(codeElement, 3);
            }
        }

        // recursively examine code elements
        private void ExamineCodeElement(CodeElement codeElement, int tabs)
        {
            tabs++;
            try
            {
                ExamineLongParameterList(codeElement);
                foreach(CodeElement childElement in codeElement.Children)
                {
                    ExamineCodeElement(childElement, tabs);
                }
            }
            catch
            {
                
            }
        }

        // vsCMElementClass	C:	emp
        private void ExamineLongParameterList(CodeElement codeElement)
        {
            int treshold = 7;
            if (codeElement.Kind == vsCMElement.vsCMElementFunction)
            {
                CodeFunction method = (CodeFunction)codeElement.StartPoint.get_CodeElement(vsCMElement.vsCMElementFunction);
                if (method.Parameters.Count > treshold)
                {
                    ShowMessage(String.Format("Long parameter list"), codeElement.StartPoint.Line);
                }

            }
        }

        //public void ParametersExample(DTE2 dte)
        //{
        //    // Before running this example, open a code document from a project
        //    // and place the insertion point inside a function.
        //    try
        //    {
        //        // Retrieve the CodeFunction at the insertion point.
        //        TextSelection sel =
        //            (TextSelection)dte.ActiveDocument.Selection;
        //        CodeFunction fun =
        //            (CodeFunction)sel.ActivePoint.get_CodeElement(
        //            vsCMElement.vsCMElementFunction);

        //        // Display the function's parameters.
        //        string parms = "";
        //        foreach (CodeParameter param in fun.Parameters)
        //        {
        //            TextPoint start =
        //                param.GetStartPoint(vsCMPart.vsCMPartWhole);
        //            TextPoint finish =
        //                param.GetEndPoint(vsCMPart.vsCMPartWhole);
        //            parms += start.CreateEditPoint().GetText(finish) +
        //                Environment.NewLine;
        //        }

        //        MessageBox.Show(fun.Name + " has the following parameters:" +
        //            Environment.NewLine + Environment.NewLine + parms);
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show(ex.Message);
        //    }
        //}


        // add a class to the given namespace
        private void AddClassToNamespace(CodeNamespace ns)
        {
            // add a class
            CodeClass2 chess = (CodeClass2)ns.AddClass("Chess", -1, null, null, vsCMAccess.vsCMAccessPublic);
            
            // add a function with a parameter and a comment
            CodeFunction2 move = (CodeFunction2)chess.AddFunction("Move", vsCMFunction.vsCMFunctionFunction, "int", -1, vsCMAccess.vsCMAccessPublic, null);
            move.AddParameter("IsOK", "bool", -1);
            move.Comment = "This is the move function";

            // add some text to the body of the function
            EditPoint2 editPoint = (EditPoint2)move.GetStartPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
            editPoint.Indent(null, 0);
            editPoint.Insert("int a = 1;");
            editPoint.InsertNewLine(1);
            editPoint.Indent(null, 3);
            editPoint.Insert("int b = 3;");
            editPoint.InsertNewLine(2);
            editPoint.Indent(null, 3);
            editPoint.Insert("return a + b; //");
        }

        private void ShowMessage(string mensagem, int line)
        {
            Window win = _applicationObject.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
            OutputWindow OW = (OutputWindow)win.Object;
            OutputWindowPane OWp;
            OWp = OW.OutputWindowPanes.Add("A New Pane");            
            OWp.OutputTaskItemString("Some task", 
                vsTaskPriority.vsTaskPriorityHigh,
                vsTaskCategories.vsTaskCategoryMisc, 
                vsTaskIcon.vsTaskIconComment, 
                "C:\temp", line, mensagem);
            OWp.ForceItemsToTaskList();
        }

        private void ShowMessage(string mensagem)
        {
            ShowMessage(mensagem, 100);
        }
    }
}
